﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using CodeCreator.CoreObj;

namespace CodeCreator
{
    public class FileToReplace
    {
        private static Regex regForObj = new Regex("\\$\\$\\{Obj\\.((.|\r|\n)*?)\\}\\$\\$", RegexOptions.IgnoreCase | RegexOptions.Singleline);
        private static Regex regForObjField = new Regex("\\$\\$\\{ObjField\\.((.|\r|\n)*?)\\}\\$\\$", RegexOptions.IgnoreCase | RegexOptions.Singleline);
        private static Regex regForObjSql = new Regex("\\$\\$\\{ObjSql\\.((.|\r|\n)*?)\\}\\$\\$", RegexOptions.IgnoreCase | RegexOptions.Singleline);
        private static Regex regForRepeatSql = new Regex("##\\{SQL((.|\r|\n)*?)\\}##", RegexOptions.IgnoreCase | RegexOptions.Singleline);
        private static Regex regForRepeatField = new Regex("##\\{FIELD((.|\r|\n)*?)\\}##", RegexOptions.IgnoreCase | RegexOptions.Singleline);
        private static Regex regForCheck = new Regex("\\$\\$\\<((.|\r|\n)*?)\\>\\$\\$", RegexOptions.IgnoreCase | RegexOptions.Singleline);
                    

        /// <summary>
        /// 模板替换
        /// </summary>
        /// <param name="filePath"></param>
        public static void replaceFile(string filePath, Obj obj)
        {
            FileInfo fileInfo = new FileInfo(filePath);
            if (fileInfo.Exists)
            {
                //读取模板
                StreamReader fStream = new StreamReader(filePath, Encoding.UTF8);
                string str = fStream.ReadToEnd();
                fStream.Close();

                //处理Sql的重复项
                MatchCollection mRepeatSql = regForRepeatSql.Matches(str);
                foreach (Match m in mRepeatSql)
                {
                    string strOld = m.Groups[0].Value;
                    string strNew = "";
                    string strValue = m.Groups[1].Value;

                    foreach (ObjSql os in obj.Sqls)
                    {
                        string strItem = strValue;
                        //处理判断
                        strItem = doCheckToObj<ObjSql>(obj,os, strItem);

                        //替换属性值
                        MatchCollection mObjSql = regForObjSql.Matches(strItem);
                        foreach (Match mOS in mObjSql)
                        {
                            object value_obj = ToolsReflect.GetValue<ObjSql>(os, mOS.Groups[1].Value);
                            if (value_obj != null)
                            {
                                strItem = strItem.Replace("$${ObjSql." + mOS.Groups[1].Value + "}$$", value_obj.ToString());
                            }
                        }
                        strNew += strItem.TrimEnd() + "\r\n";
                    }
                    if (strNew.EndsWith(",\r\n"))
                        strNew = strNew.Substring(0, strNew.Length - 3) + "\r\n";
                    str = str.Replace(strOld, strNew);
                }

                //处理Field的重复项
                MatchCollection mRepeatField = regForRepeatField.Matches(str);
                foreach (Match m in mRepeatField)
                {
                    string strOld = m.Groups[0].Value;
                    string strNew = "";
                    string strValue = m.Groups[1].Value;

                    foreach (ObjField of in obj.Fields)
                    {
                        string strItem = strValue;
                        //处理判断
                        strItem = doCheckToObj<ObjField>(obj, of, strItem);

                        //替换属性值
                        MatchCollection mObjField = regForObjField.Matches(strItem);
                        foreach (Match mOF in mObjField)
                        {
                            object value_obj = ToolsReflect.GetValue<ObjField>(of, mOF.Groups[1].Value);
                            if (value_obj != null)
                            {
                                strItem = strItem.Replace("$${ObjField." + mOF.Groups[1].Value + "}$$", value_obj.ToString());
                            }
                        }
                        strNew += strItem.TrimEnd()+"\r\n";
                    }
                    if (strNew.EndsWith(",\r\n"))
                        strNew = strNew.Substring(0, strNew.Length - 3) + "\r\n";

                    str = str.Replace(strOld, strNew);
                }

                //处理判断
                str = doCheckToObj<Obj>(obj, obj, str);
                //处理Obj后以的整体替换
                MatchCollection mObj = regForObj.Matches(str);
                foreach (Match m in mObj)
                {
                    object value_obj = ToolsReflect.GetValue<Obj>(obj, m.Groups[1].Value);
                    if (value_obj != null)
                    {
                        str = str.Replace("$${Obj." + m.Groups[1].Value + "}$$", value_obj.ToString());
                    }
                }

                //修改文件名
                string strFileName = fileInfo.Name;
                MatchCollection mFileName = regForObj.Matches(strFileName);
                foreach (Match m in mFileName)
                {
                    object value_obj = ToolsReflect.GetValue<Obj>(obj, m.Groups[1].Value);
                    if (value_obj != null)
                    {
                        strFileName = strFileName.Replace("$${Obj." + m.Groups[1].Value + "}$$", value_obj.ToString());
                    }
                }

                //保存文件
                StreamWriter sw = new StreamWriter(fileInfo.Directory + "\\" + strFileName);
                sw.Write(str);
                sw.Flush();
                sw.Close();

                if (strFileName == fileInfo.Name)
                {
                    //删除原文件
                    fileInfo.CopyTo(fileInfo.DirectoryName + "\\" + obj.ClassName + "_" + strFileName, true);
                }
            }
        }

        /// <summary>
        /// 处理判断模块
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <param name="str"></param>
        /// <returns></returns>
        private static string doCheckToObj<T>(Obj obj,T objT, string str)
        {
            Regex regForCheck = new Regex("\\$\\$\\<((.|\r|\n)*?)\\>\\$\\$", RegexOptions.IgnoreCase | RegexOptions.Singleline);
            MatchCollection mCheck = regForCheck.Matches(str);
            if (mCheck.Count > 0)
            {
                foreach (Match m in mCheck)
                {
                    string strOld = m.Groups[0].Value;
                    string strNew = "";
                    string strValue = m.Groups[1].Value.Trim();
                    string strCheck = strValue.Substring(strValue.IndexOf('(') + 1, strValue.IndexOf(')') - strValue.IndexOf('(') - 1);
                    //判断函数是否需要生成代码
                    if (CheckStringEqual<T>(obj, objT, strCheck))
                    {
                        strNew = strValue.Replace("(" + strCheck + ")", "");
                        strNew = ToolsFile.RemoveBeforeEnter(strNew);
                        str = ToolsFile.ReplaceAndRemoveAfterEnter(str, strOld, strNew); 
                    }
                    else
                    {
                        //处理掉换行
                        strNew = "";
                        str = ToolsFile.ReplaceAndRemoveAfterEnter(str, strOld, strNew);
                    }
                }
            }
            return str;
        }

        /// <summary>
        /// 拆分判断公式，返回是否生成该断代码
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static bool CheckStringEqual<T>(Obj obj, T objT, string str)
        {
            str = str.Trim();

            if (str.IndexOf("!=") > 0)
            {
                str = str.Replace("!=", "!");
                string[] ss = str.Split('!');
                if (ss.Length == 2)
                {
                    if (CheckStringEqual<T>(obj,objT,ss[0],ss[1]))
                        return false;
                    else
                        return true;
                }
                else
                {
                    return false;
                }
            }
            else if (str.IndexOf('=') > 0)
            {
                string[] ss = str.Split('=');
                if (ss.Length == 2)
                {
                    if (CheckStringEqual<T>(obj, objT, ss[0], ss[1]))
                        return true;
                    else
                        return false;
                }
                else
                {
                    return false;
                }
            }
            else
                return false;
        }

        /// <summary>
        /// 判断两个Str是否相等
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <param name="objT"></param>
        /// <param name="str1"></param>
        /// <param name="str2"></param>
        /// <returns></returns>
        public static bool CheckStringEqual<T>(Obj obj, T objT, string str1, string str2)
        {
            if (str1.StartsWith("Obj."))
            {
                str1 = str1.Substring(str1.IndexOf('.') + 1, str1.Length - str1.IndexOf('.') -1);
                str1 = ToolsReflect.GetValueToString<Obj>(obj, str1);
            }
            else
            {
                str1 = str1.Substring(str1.IndexOf('.') + 1, str1.Length - str1.IndexOf('.') - 1);
                str1 = ToolsReflect.GetValueToString<T>(objT, str1);
            }

            if (str2 == "")
            {
                if (str1 == ""||str1 == null)
                    return true;
                else
                    return false;
            }
            else
            {
                if (str1.ToUpper() == str2.ToUpper())
                    return true;
                else
                    return false;
            }
        }
    }
}
